home *** CD-ROM | disk | FTP | other *** search
- // bits.h
-
- #include <iostream.h>
- #include <stddef.h>
- #include <limits.h>
- #include <assert.h>
- #include "string.hpp"
-
- template<size_t N>
- class bits
- {
- // Global I/O funtions
- friend ostream& operator<<(ostream& os, const bits<N>& rhs)
- {os << rhs.to_string(); return os;}
- friend istream& operator>>(istream& is, bits<N>& rhs)
- {rhs.read(is); return is;}
-
- // Global bitwise operators
- friend bits<N> operator&(const bits<N>& b1,const bits<N>&
- b2)
- {bits<N> r(b1); return r &= b2;}
- friend bits<N> operator|(const bits<N>& b1,const bits<N>&
- b2)
- {bits<N> r(b1); return r |= b2;}
- friend bits<N> operator^(const bits<N>& b1,const bits<N>&
- b2)
- {bits<N> r(b1); return r ^= b2;}
-
- public:
- // Constructors
- bits();
- bits(unsigned long n);
- bits(const bits<N>& b);
- bits(const string& s);
-
- // Conversions
- unsigned short to_ushort() const;
- unsigned long to_ulong() const;
- string to_string() const;
-
- // Assignment
- bits<N>& operator=(const bits<N>& rhs);
-
- // Equality
- int operator==(const bits<N>& rhs) const;
- int operator!=(const bits<N>& rhs) const;
-
- // Basic bit operations
- bits<N>& set(size_t pos, int val = 1);
- bits<N>& set();
- bits<N>& reset(size_t pos);
- bits<N>& reset();
- bits<N>& toggle(size_t pos);
- bits<N>& toggle();
- bits<N> operator~() const;
- int test(size_t n) const;
- int any() const;
- int none() const;
-
- // Bit-wise operators
-
- bits<N>& operator&=(const bits<N>& rhs);
- bits<N>& operator|=(const bits<N>& rhs);
- bits<N>& operator^=(const bits<N>& rhs);
-
- // Shift operators
- bits<N>& operator<<=(size_t n);
- bits<N>& operator>>=(size_t n);
- bits<N> operator<<(size_t n) const;
- bits<N> operator>>(size_t n) const;
-
- size_t count() const;
- size_t length() const;
-
- private:
- typedef unsigned int Block;
- enum {BLKSIZ = CHAR_BIT * sizeof (Block)};
- enum {nblks_ = (N+BLKSIZ-1) / BLKSIZ};
-
- Block bits_[nblks_];
-
- static size_t word(size_t pos)
- {return nblks_ - 1 - pos/BLKSIZ;}
- static size_t offset(size_t pos)
- {return pos % BLKSIZ;}
- static Block mask1(size_t pos)
- {return Block(1) << offset(pos);}
- static Block mask0(size_t pos)
- {return ~(Block(1) << offset(pos));}
-
- void cleanup();
- void set_(size_t pos);
- int set_(size_t pos, int val);
- void reset_(size_t pos);
- int test_(size_t pos) const;
- void from_string(const string& s);
- void read(istream& is);
- int any(size_t start_pos) const;
- unsigned long to(size_t) const;
- };
-
- template<size_t N>
- inline bits<N>::bits()
- {
- reset();
- }
-
- template<size_t N>
- bits<N>::bits(const string& s)
- {
- // Validate that s has only 0's and 1's
- for (int i = 0; i < s.length(); ++i)
- {
- char c = s.get_at(i);
- if (c != '0' && c != '1')
- break;
- }
- assert(i == s.length());
-
- from_string(s);
- }
-
- template<size_t N>
- inline bits<N>::bits(const bits<N>& b)
- {
- memcpy(bits_,b.bits_,nblks_*sizeof(bits_[0]));
- }
-
- template<size_t N>
- bits<N>::bits(unsigned long n)
- {
- // Don't drop any bits
- if (N < CHAR_BIT * sizeof(unsigned long))
- assert((n >> N) == 0);
- reset();
-
- size_t nblks = sizeof (unsigned long) / sizeof (Block);
- if (nblks > 1)
- for (int i = 0; i < nblks; ++i)
- {
- bits_[nblks_ - 1 - i] = Block(n);
- n >>= BLKSIZ;
- }
- else
- bits_[nblks_ - 1] = Block(n);
- }
-
- template<size_t N>
- unsigned short bits<N>::to_ushort() const
- {
- size_t limit = sizeof(unsigned short) * CHAR_BIT;
- assert(!(length() > limit && any(limit)));
- size_t nblks = sizeof(unsigned short) / sizeof(Block);
- return (unsigned short) to(nblks);
- }
- template<size_t N>
- unsigned long bits<N>::to_ulong() const
- {
- size_t limit = sizeof(unsigned long) * CHAR_BIT;
- assert(!(length() > limit && any(limit)));
- size_t nblks = sizeof(unsigned long) / sizeof(Block);
- return to(nblks);
- }
-
- template<size_t N>
- string bits<N>::to_string() const
- {
- char *s = new char[N+1];
- for (int i = 0; i < N; ++i)
- s[i] = '0' + test_(N-1-i);
- s[N] = '\0';
- string s2(s);
- delete [] s;
- return s2;
- }
-
- template<size_t N>
- bits<N>& bits<N>::operator=(const bits<N>& b)
- {
- if (this != &b)
- memcpy(bits_,b.bits_, nblks_ * sizeof(bits_[0]));
- return *this;
- }
-
- template<size_t N>
- inline int bits<N>::operator==(const bits<N>& b) const
- {
- return !memcmp(bits_,b.bits_,nblks_ * sizeof(bits_[0]));
- }
-
- template<size_t N>
- inline int bits<N>::operator!=(const bits<N>& b) const
- {
- return !operator==(b);
- }
-
- template<size_t N>
- inline bits<N>& bits<N>::set(size_t pos, int val)
- {
- assert(pos < N);
- (void) set_(pos,val);
- return *this;
- }
-
- template<size_t N>
- inline bits<N>& bits<N>::set()
- {
- memset(bits_,~0u,nblks_ * sizeof bits_[0]);
- cleanup();
- return *this;
- }
-
- template<size_t N>
- inline bits<N>& bits<N>::reset(size_t pos)
- {
- assert(pos < N);
- reset_(pos);
- return *this;
- }
-
- template<size_t N>
- inline bits<N>& bits<N>::reset()
- {
- memset(bits_,0,nblks_ * sizeof bits_[0]);
- return *this;
- }
-
- template<size_t N>
- inline bits<N>& bits<N>::toggle(size_t pos)
- {
- assert(pos < N);
- bits_[word(pos)] ^= mask1(pos);
- return *this;
- }
-
- template<size_t N>
- bits<N>& bits<N>::toggle()
- {
- size_t nw = nblks_;
- while (nw--)
-
- bits_[nw] = ~bits_[nw];
- cleanup();
- return *this;
- }
-
- template<size_t N>
- inline bits<N> bits<N>::operator~() const
- {
- bits<N> b(*this);
- b.toggle();
- return b;
- }
-
- template<size_t N>
- inline int bits<N>::test(size_t pos) const
- {
- assert(pos < N);
- return test_(pos);
- }
-
- template<size_t N>
- int bits<N>::any() const
- {
- for (int i = 0; i < nblks_; ++i)
- if (bits_[i])
- return 1;
- return 0;
- }
-
- template<size_t N>
- inline int bits<N>::none() const
- {
- return !any();
- }
-
- template<size_t N>
- bits<N>& bits<N>::operator&=(const bits<N>& rhs)
- {
- for (int i = 0; i < nblks_; ++i)
- bits_[i] &= rhs.bits_[i];
- return *this;
- }
-
- template<size_t N>
- bits<N>& bits<N>::operator|=(const bits<N>& rhs)
- {
- for (int i = 0; i < nblks_; ++i)
- bits_[i] |= rhs.bits_[i];
- return *this;
- }
-
- template<size_t N>
- bits<N>& bits<N>::operator^=(const bits<N>& rhs)
- {
- for (int i = 0; i < nblks_; ++i)
- bits_[i] ^= rhs.bits_[i];
- return *this;
- }
-
- template<size_t N>
-
- bits<N>& bits<N>::operator>>=(size_t n)
- {
- if (n > N)
- n = N;
- for (int i = 0; i < N-n; ++i)
- (void) set_(i,test_(i+n));
- for (i = N-n; i < N; ++i)
- reset_(i);
- return *this;
- }
-
- template<size_t N>
- bits<N>& bits<N>::operator<<=(size_t n)
- {
- if (n > N)
- n = N;
- for (int i = N-1; i >= n; --i)
- (void) set_(i,test(i-n));
- for (i = 0; i < n; ++i)
- reset_(i);
- return *this;
- }
-
- template<size_t N>
- inline bits<N> bits<N>::operator>>(size_t n) const
- {
- bits r(*this);
- return r >>= n;
- }
-
- template<size_t N>
- inline bits<N> bits<N>::operator<<(size_t n) const
- {
- bits r(*this);
- return r <<= n;
- }
-
- template<size_t N>
- size_t bits<N>::count() const
- {
- size_t sum = 0;
- for (int i = 0; i < N; ++i)
- if (test_(i))
- ++sum;
- return sum;
- }
-
- template<size_t N>
- inline size_t bits<N>::length() const
- {
- return N;
- }
-
- // Private functions
- template<size_t N>
- inline void bits<N>::set_(size_t pos)
- {
- bits_[word(pos)] |= mask1(pos);
- }
-
-
- template<size_t N>
- int bits<N>::set_(size_t pos, int val)
- {
- if (val)
- set_(pos);
- else
- reset_(pos);
- return !!val;
- }
-
- template<size_t N>
- inline void bits<N>::reset_(size_t pos)
- {
- bits_[word(pos)] &= mask0(pos);
- }
-
- template<size_t N>
- inline int bits<N>::test_(size_t pos) const
- {
- return !!(bits_[word(pos)] & mask1(pos));
- }
-
- template<size_t N>
- inline void bits<N>::cleanup()
- {
- // Make sure unused bits don't get set
- bits_[0] &= (~Block(0) >> (nblks_ * BLKSIZ - N));
- }
-
- template<size_t N>
- void bits<N>::from_string(const string& s)
- {
- // Assumes s contains only 0's and 1's
- size_t slen = s.length();
- reset();
- for (int i = slen-1; i >= 0; --i)
- if (s.get_at(i) == '1')set_(slen-i-1);
- }
-
- template<size_t N>
- void bits<N>::read(istream& is)
- {
- char *buf = new char[N];
- char c;
-
- is >> ws;
- for (int i = 0; i < N; ++i)
- {
- is.get(c);
- if (c == '0' || c == '1')
- buf[i] = c;
- else
- {
- is.putback(c);
- buf[i] = '\0';
- break;
- }
- }
-
-
- if (i == 0)
- is.clear(ios::failbit);
- else
- from_string(string(buf));
-
- delete buf;
- }
-
- template<size_t N>
- int bits<N>::any(size_t start) const
- {
- // See if any bit past start (inclusive) is set
- for (int i = start; i < N; ++i)
- if (test_(i))
- return 1;
- return 0;
- }
-
- template<size_t N>
- unsigned long bits<N>::to(size_t nblks) const
- {
- if (nblks > 1)
- {
- int i;
- unsigned long n = bits_[nblks_ - nblks];
-
- /* Collect low-order sub-blocks into an unsigned */
- if (nblks > nblks_)
- nblks = nblks_;
- while (--nblks)
- n = (n << BLKSIZ) | bits_[nblks_ - nblks];
- return n;
- }
- else
- return (unsigned long) bits_[nblks_ - 1];
- }
-
- /* End of File */
-
-